--[[## ft=lua ##################################################################
  This file is licensed under [WTFPL v2](https://www.wtfpl.net/).  You may read
  the full license in the file LICENSE or by following the web link.

  TAG - arbitrary tagging facilities for tables and userdata

  Notes on implementation:

  I've resisted the urge to use tag to add a metatable with the set operations
  bundled inside simply as being too heavyweight for such a lightweight concept.
  `tag` is implemented in the simplest, most straightforward way possible
  without being obtrusive on the value's behaviour anywhere else.  Thus the tags
  themselves are, indeed, stored in the metatable, but the operations are
  external.
--############################################################################]]

local set = require 'set'

local function add(t, ...)
    old_mt = getmetatable(t) or {}
    old_mt.__tag_table = old_mt.__tag_table or set()
    old_mt.__tag_table:batch_insert(...)
    setmetatable(t, old_mt)
end

local function remove(t, ...)
    old_mt = getmetatable(t) or {}
    old_mt.__tag_table = old_mt.__tag_table or set()
    old_mt.__tag_table:batch_remove(...)
    setmetatable(t, old_mt)
end

local function has_tag(t, v)
    return  (getmetatable(t) and getmetatable(t).__tag_table and getmetatable(t).__tag_table:has(v)) or false
end

return setmetatable({}, {
    __index = {
        add = add,
        remove = remove,
        has_tag = has_tag,
    }
})
